import os
import webbrowser
from tkinter import filedialog, messagebox
from tkinter import scrolledtext

import ttkbootstrap as ttk
from PIL import Image, ImageTk
from PyPDF2 import PdfReader, PdfWriter
from reportlab.lib.pagesizes import A4
from reportlab.pdfgen import canvas
from ttkbootstrap.constants import *


class PDFAddImagePage(ttk.Frame):
    def __init__(self, master):
        super().__init__(master)
        self.pdf_path = None
        self.image_paths = []
        self.setup_ui()

    def setup_ui(self):
        # 创建PDF上传区域
        pdf_frame = ttk.LabelFrame(self, text="PDF文件")
        pdf_frame.pack(fill=X, padx=10, pady=5)

        self.pdf_upload_btn = ttk.Button(
            pdf_frame,
            text="上传PDF",
            command=self.upload_pdf,
            style="primary.TButton"
        )
        self.pdf_upload_btn.pack(side=LEFT, padx=5, pady=5)

        self.pdf_path_label = ttk.Label(pdf_frame, text="未选择PDF文件")
        self.pdf_path_label.pack(side=LEFT, padx=5, pady=5)

        self.pdf_preview_btn = ttk.Button(
            pdf_frame,
            text="预览",
            command=self.preview_pdf,
            style="info.TButton",
            state=DISABLED
        )
        self.pdf_preview_btn.pack(side=LEFT, padx=5, pady=5)

        # 创建图片上传区域
        image_frame = ttk.LabelFrame(self, text="图片文件")
        image_frame.pack(fill=X, padx=10, pady=5)

        self.image_upload_btn = ttk.Button(
            image_frame,
            text="上传图片",
            command=self.upload_images,
            style="primary.TButton"
        )
        self.image_upload_btn.pack(side=LEFT, padx=5, pady=5)

        # 显示已上传图片列表
        self.image_list = scrolledtext.ScrolledText(
            image_frame,
            width=50,
            height=5,
            wrap=ttk.WORD
        )
        self.image_list.pack(padx=5, pady=5, fill=X)
        self.image_list.config(state=DISABLED)

        # 转换按钮
        self.convert_btn = ttk.Button(
            self,
            text="开始转换",
            command=self.add_images_to_pdf,
            style="success.TButton",
            state=DISABLED
        )
        self.convert_btn.pack(pady=10)

        # 进度条
        self.progress = ttk.Progressbar(
            self,
            mode='determinate',
            length=300
        )
        self.progress.pack(pady=10)

        # 导出文件信息
        self.export_frame = ttk.LabelFrame(self, text="导出文件")
        self.export_frame.pack(fill=X, padx=10, pady=10)

        self.export_path_label = ttk.Label(self.export_frame, text="未导出文件")
        self.export_path_label.pack(side=LEFT, padx=5)

        self.preview_export_btn = ttk.Button(
            self.export_frame,
            text="预览",
            command=self.preview_export,
            style="info.TButton",
            state=DISABLED
        )
        self.preview_export_btn.pack(side=LEFT, padx=5)

    def upload_pdf(self):
        file_path = filedialog.askopenfilename(
            filetypes=[("PDF文件", "*.pdf")]
        )
        if file_path:
            self.pdf_path = file_path
            self.pdf_path_label.config(text=file_path)
            self.pdf_preview_btn.config(state=NORMAL)
            self.update_convert_button_state()

    def preview_pdf(self):
        try:
            webbrowser.open(self.pdf_path)
        except Exception as e:
            messagebox.showerror("错误", f"预览失败：{str(e)}")

    def upload_images(self):
        file_paths = filedialog.askopenfilenames(
            filetypes=[("图片文件", "*.png *.jpg *.jpeg *.bmp *.gif")]
        )
        if file_paths:
            self.image_paths.extend(file_paths)
            self.update_image_list()
            self.update_convert_button_state()

    def update_image_list(self):
        self.image_list.config(state=NORMAL)
        self.image_list.delete(1.0, ttk.END)

        for i, image_path in enumerate(self.image_paths, 1):
            self.image_list.insert(ttk.END, f"{i}. {os.path.basename(image_path)}\n")

            # 添加操作按钮
            btn_frame = ttk.Frame(self.image_list)
            self.image_list.window_create(ttk.END, window=btn_frame)

            # 预览按钮
            preview_btn = ttk.Button(
                btn_frame,
                text="预览",
                command=lambda path=image_path: self.preview_image(path),
                style="info.TButton",
                width=5
            )
            preview_btn.pack(side=LEFT, padx=2)

            # 删除按钮
            delete_btn = ttk.Button(
                btn_frame,
                text="删除",
                command=lambda idx=i - 1: self.delete_image(idx),
                style="danger.TButton",
                width=5
            )
            delete_btn.pack(side=LEFT, padx=2)

            # 上移按钮
            if i > 1:
                up_btn = ttk.Button(
                    btn_frame,
                    text="↑",
                    command=lambda idx=i - 1: self.move_image(idx, -1),
                    style="primary.TButton",
                    width=2
                )
                up_btn.pack(side=LEFT, padx=2)

            # 下移按钮
            if i < len(self.image_paths):
                down_btn = ttk.Button(
                    btn_frame,
                    text="↓",
                    command=lambda idx=i - 1: self.move_image(idx, 1),
                    style="primary.TButton",
                    width=2
                )
                down_btn.pack(side=LEFT, padx=2)

            self.image_list.insert(ttk.END, "\n")

        self.image_list.config(state=DISABLED)

    def preview_image(self, image_path):
        try:
            preview_window = ttk.Toplevel(self)
            preview_window.title("图片预览")

            img = Image.open(image_path)
            # 调整图片大小以适应窗口
            max_size = (600, 600)
            img.thumbnail(max_size, Image.Resampling.LANCZOS)

            photo = ImageTk.PhotoImage(img)
            label = ttk.Label(preview_window, image=photo)
            label.image = photo
            label.pack(padx=10, pady=10)
        except Exception as e:
            messagebox.showerror("错误", f"预览失败：{str(e)}")

    def delete_image(self, index):
        del self.image_paths[index]
        self.update_image_list()
        self.update_convert_button_state()

    def move_image(self, index, direction):
        if 0 <= index + direction < len(self.image_paths):
            self.image_paths[index], self.image_paths[index + direction] = \
                self.image_paths[index + direction], self.image_paths[index]
            self.update_image_list()

    def update_convert_button_state(self):
        if self.pdf_path and self.image_paths:
            self.convert_btn.config(state=NORMAL)
        else:
            self.convert_btn.config(state=DISABLED)

    def add_images_to_pdf(self):
        if not self.pdf_path or not self.image_paths:
            messagebox.showerror("错误", "请先上传PDF文件和图片")
            return

        # 获取PDF文件名作为默认输出文件名
        default_name = os.path.splitext(os.path.basename(self.pdf_path))[0] + "_with_images.pdf"

        output_path = filedialog.asksaveasfilename(
            defaultextension=".pdf",
            filetypes=[("PDF文件", "*.pdf")],
            initialfile=default_name
        )

        if not output_path:
            return

        # 检查文件是否存在
        if os.path.exists(output_path):
            if not messagebox.askyesno("确认", "文件已存在，是否覆盖？"):
                return

        try:
            self.progress['value'] = 0
            self.update_idletasks()

            # 读取原始PDF
            reader = PdfReader(self.pdf_path)
            writer = PdfWriter()

            # 复制所有页面
            for page in reader.pages:
                writer.add_page(page)

            # 添加图片到新页面
            for i, image_path in enumerate(self.image_paths):
                # 创建临时PDF文件
                temp_pdf = f"temp_{i}.pdf"
                c = canvas.Canvas(temp_pdf, pagesize=A4)

                # 打开并处理图片
                img = Image.open(image_path)
                img_width, img_height = img.size
                page_width, page_height = A4

                # 计算图片大小和位置
                ratio = min(page_width / img_width, page_height / img_height)
                new_width = img_width * ratio
                new_height = img_height * ratio

                # 居中显示
                x = (page_width - new_width) / 2
                y = (page_height - new_height) / 2

                # 绘制图片
                c.drawImage(image_path, x, y, width=new_width, height=new_height)
                c.save()

                # 将图片页面添加到PDF
                img_reader = PdfReader(temp_pdf)
                writer.add_page(img_reader.pages[0])

                # 删除临时文件
                os.remove(temp_pdf)

                # 更新进度
                progress = (i + 1) / len(self.image_paths) * 100
                self.progress['value'] = progress
                self.update_idletasks()

            # 设置PDF标题
            title = os.path.splitext(os.path.basename(output_path))[0]
            writer.add_metadata({'/Title': title})

            # 保存最终PDF
            with open(output_path, 'wb') as output_file:
                writer.write(output_file)

            self.progress['value'] = 100
            self.update_idletasks()

            # 更新导出文件信息
            self.export_path_label.config(text=output_path)
            self.preview_export_btn.config(state=NORMAL)

            messagebox.showinfo("成功", "图片已添加到PDF并保存")

        except Exception as e:
            messagebox.showerror("错误", f"添加图片失败：{str(e)}")
        finally:
            self.progress['value'] = 0

    def preview_export(self):
        try:
            webbrowser.open(self.export_path_label.cget("text"))
        except Exception as e:
            messagebox.showerror("错误", f"预览失败：{str(e)}")
